#import "ALConstants.h"
#import "NSManagedObject+SMRAdditions.h"
#import "ALEntry.h"
#import "ALElement.h"
#import "ALEntry+DisplayAdditions.h"
#import "NSAttributedString+SMRAdditions.h"
#import "NSManagedObjectContext+SMRAdditions.h"


#pragma mark -
#pragma mark Entity keys

NSString* const ALAppEntity = @"ALApp";
NSString* const ALVersionEntity = @"ALVersion";
NSString* const ALEntryEntity = @"ALEntry";


#pragma mark -
#pragma mark Property keys

NSString* const ALTitleKey = @"title";
NSString* const ALAppIconKey = @"icon";
NSString* const ALAppTypeKey = @"appType";
NSString* const ALReleaseDateKey = @"releaseDate";
NSString* const ALAppKey = @"app";
NSString* const ALVersionsKey = @"versions";
NSString* const ALLabelKey = @"label";
NSString* const ALEntryKey = @"entry";
NSString* const ALEntriesKey = @"entries";
NSString* const ALVersionKey = @"version";
NSString* const ALElementValueKey = @"elementValue";
NSString* const ALCurrentAppKey = @"currentApp";


#pragma mark String constant keys

NSString* const ALBundleIdentifierKey = @"bundleIdentifier";
NSString* const ALEntryViewKey = @"view";
NSString* const ALDefaultTemplatesFile = @"ALDefaultTemplates.plist";
NSString* const ALDefaultEntryFiltersFile = @"ALDefaultEntryFilters.plist";
NSString* const ALAttachmentURLStringKey = @"attachmentURLString";
NSString* const ALLineNumberKey = @"lineNumber";
NSString* const ALElementTypeKey = @"elementType";
NSString* const ALElementTemplatesKey = @"elementTemplates";
NSString* const ALInfoPListKey = @"infoPListKey";
NSString* const ALEntryDescriptionKey = @"entryDescription";
NSString* const ALDataValueKey = @"dataValue";
NSString* const ALRepresentedObjectKey = @"representedObject";
NSString* const ALTemplateEditorNothingSelected = @"Nothing Selected";
NSString* const ALTemplateEditorMultipleSelection = @"Multiple Entries Selected";
NSString* const kALSelectedAppsKey = @"ALSelectedApps";
NSString* const ALTemplateKey = @"template";
NSString* const ALTextPropertyWrapsKey = @"textPropertyWrapping";
NSString* const ALParentEntryKey = @"parentEntry";
NSString* const ALSelectedKey = @"selected";
NSString* const kALDetailToolbarAllGroupIdentifier = @"ALDetailAllGroup";
NSString* const kALDetailToolbarTagGroupIdentifier = @"ALDetailTagGroup";
NSString* const kALDetailToolbarCustomGroupIdentifier = @"ALDetailCustomGroup";
NSString* const kALVersionsFilterKey = @"ALVersionsFilter";
NSString* const kALVersionsFilterBeginDateKey = @"ALVersionsFilterBeginDate";
NSString* const kALVersionsFilterEndDateKey = @"ALVersionsFilterEndDate";
NSString* const kALSelectedEntryFilterTitleKey = @"ALSelectedEntryFilterTitle";
//NSString* const kALSelectedEntryFilterKey = @"ALSelectedEntryFilter";


#pragma mark -
#pragma mark Generic string constants
NSString* const ALArrangedObjectsKey = @"arrangedObjects";
NSString* const ALFrameOriginKey = @"frameOrigin";
NSString* const ALFrameSizeKey = @"frameSize";
NSString* const ALBoundsKey = @"bounds";
NSString* const ALOpacityKey = @"opacity";
NSString* const ALSelectionIndexesKey = @"selectionIndexes";


#pragma mark -
#pragma mark Number constants

CGFloat const ALElementFontSizePrimary = 13.0f;
CGFloat const ALElementFontSizeSecondary = 11.0f;
ALDetailMode const kALMinDetailMode = ALModeEvent;
ALDetailMode const kALMaxDetailMode = ALModeChart;


#pragma mark -
#pragma mark Defaults

NSString* const ALModeSelection = @"ALModeSelection";
NSString* const ALToolbarVisible = @"ALToolbarVisible";
NSString* const ALToolbarShowsTitles = @"ALToolbarShowsTitles";
NSString* const ALEditTemplateViewHeight = @"ALEditTemplateViewHeight";
NSString* const ALTemplateEditorIsVisible = @"ALTemplateEditorIsVisible";
NSString* const ALTemplateFiltersKey = @"ALTemplateFiltersKey";
//NSString* const ALInfoViewIsVisible = @"ALInfoViewIsVisible";
NSString* const ALInfoViewLastWidthBeforeCloseKey = @"ALInfoViewLastWidthBeforeClose";
NSString* const ALChartInfoAppCriteria = @"ALChartInfoAppCriteria";


#pragma mark -
#pragma mark Notifications

NSString* const ALModeDidChangeNotification = @"ALModeDidChangeNotification";
NSString* const ALNewMode = @"ALNewMode";
NSString* const ALCustomEntryFilterDidChangeNotification = @"ALCustomEntryFilterDidChange";


#pragma mark -
#pragma mark Utility functions

CGPoint SMRIntegralPoint(CGPoint aPoint) {
    return CGPointMake(roundf(aPoint.x), roundf(aPoint.y));
}


#pragma mark -
#pragma mark Quicklook caching functions

NSString* ALQuickLookCacheDirectory() {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
    NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : NSTemporaryDirectory();
    NSString *cacheDirectory = [basePath stringByAppendingPathComponent:@"Angel/QuickLookCache"];
	
	NSFileManager *fileManager = [[[NSFileManager alloc] init] autorelease];
	if ([fileManager fileExistsAtPath:cacheDirectory isDirectory:NULL]) 
		return cacheDirectory;
	
	NSError *error = nil;
	if (![fileManager createDirectoryAtPath:cacheDirectory withIntermediateDirectories:YES attributes:nil error:&error]) {
		[[NSApplication sharedApplication] presentError:error];
		return nil;
	}
	return cacheDirectory;
}

NSURL* CacheURLForEntry(ALEntry* entry) {
	NSString *cacheDirectory = ALQuickLookCacheDirectory();
	NSString *entryString = [[entry smrURIRepresentation] lastPathComponent];
	entryString = [entryString stringByAppendingPathExtension:@"rtfd"];
	NSString *itemPath = [cacheDirectory stringByAppendingPathComponent:entryString];
	NSURL *entryURL = [NSURL fileURLWithPath:itemPath];
	return entryURL;
}

NSArray* AttachmentURLsForEntry(ALEntry *entry) {
	NSMutableArray *urlArray = [NSMutableArray array];
	NSSet *elements = [entry elements];
	NSSet *filteredElements = [elements filteredSetUsingPredicate:[NSPredicate predicateWithFormat:@"elementType = %i", ALElementTypeAttachment]];
	for (ALElement *element in filteredElements) {
		NSURL *elementURL = [element attachmentURL];
		[urlArray addObject:elementURL];
	}
	return urlArray;
}

void WriteCacheFilesForEntries(NSArray* entries) {
	for (ALEntry *entry in entries) {
		NSURL *entryURL = CacheURLForEntry(entry);
		NSError *error = nil;
		NSFileManager *fileManager = [[NSFileManager alloc] init];
		if ([fileManager fileExistsAtPath:[entryURL path]] && ![fileManager removeItemAtURL:entryURL error:&error])
			[NSApp presentError:error];
		NSAttributedString *contentString = [entry attributedStringForDisplay];
		NSDictionary *attributes = [NSDictionary dictionaryWithObject:NSRTFDTextDocumentType forKey:NSDocumentTypeDocumentAttribute];
		NSFileWrapper *fileWrapper = [contentString fileWrapperFromRange:[contentString smrFullRange] documentAttributes:attributes error:&error];
		if (!fileWrapper) 
			[NSApp presentError:error];
		if (![fileWrapper writeToURL:entryURL options:0 originalContentsURL:nil error:&error]) 
			[NSApp presentError:error];
	}
}

void ClearQuicklookCacheFiles() {
	NSFileManager *fileManager = [[NSFileManager alloc] init];
	NSError *error = nil;
	NSString *cacheDirectoryRaw = ALQuickLookCacheDirectory();
	NSString *cacheDirectory = [cacheDirectoryRaw stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
	NSURL *cacheDirectoryURL = [NSURL URLWithString:cacheDirectory];
	NSArray *cacheFileURLs = [fileManager contentsOfDirectoryAtURL:cacheDirectoryURL includingPropertiesForKeys:nil options:0 error:&error];
	if (!cacheFileURLs)
		[NSApp presentError:error];
	for (NSURL *url in cacheFileURLs) {
		if (![fileManager removeItemAtURL:url error:&error])
			[NSApp presentError:error];
	}
}

//extern NSArray* CurrentVersionsForDetailMode(ALDetailMode detailMode, NSManagedObjectContext *moc) {
//    NSArray *selectedAppURIStrings = [[NSUserDefaults standardUserDefaults] arrayForKey:kALSelectedAppsKey];
//    NSArray *selectedApps = [moc smrObjectsWithURIStrings:selectedAppURIStrings];
//    NSArray *selectedVersions = [selectedApps valueForKeyPath:@"@distinctUnionOfObjects.versions"];
//    NSString *filterKey = [NSString stringWithFormat:@"%@.%ld", kALVersionsFilterKey, detailMode];
//    ALVersionsFilterMode filterMode = [[NSUserDefaults standardUserDefaults] integerForKey:filterKey];
//    NSPredicate *filterPredicate = nil;
//    NSDate *beginDate = nil;
//    NSDate *endDate = nil;
//    NSArray *filterDates = nil;
//    switch (filterMode) {
//        case ALVersionsFilterModeCurrent:
//            filterPredicate = [NSPredicate predicateWithFormat:@"currentApp != nil"];
//            break;
//        case ALVersionsFilterModeDate:
//            beginDate = [[NSUserDefaults standardUserDefaults] objectForKey:kALVersionsFilterBeginDateKey];
//            if (!beginDate)
//                beginDate = [NSDate distantPast];
//            endDate = [[NSUserDefaults standardUserDefaults] objectForKey:kALVersionsFilterEndDateKey];
//            if (!endDate)
//                endDate = [NSDate distantFuture];
//            filterDates = [NSArray arrayWithObjects:beginDate, endDate, nil];
//            filterPredicate = [NSPredicate predicateWithFormat:@"releaseDate BETWEEN %@", filterDates];
//            break;
//        default:  // ALVersionsFilterModeAll will leave filterPredicate == nil
//            break;
//    }
//    NSArray *filteredVersions = [selectedVersions filteredArrayUsingPredicate:filterPredicate];
//    return filteredVersions;
//}

